package com.ayf.payment.game.api.channel.alipay.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.cache.redis.RedisCacheUtil;
import com.ayf.payment.game.api.channel.alipay.AlipayApiException;
import com.ayf.payment.game.api.channel.alipay.response.AlipayFundAccountQueryResponse;
import com.ayf.payment.game.api.channel.alipay.response.AlipayFundTransCommonQueryResponse;
import com.ayf.payment.game.api.channel.alipay.response.AlipayFundTransUniTransferResponse;
import com.ayf.payment.game.api.channel.alipay.util.AlipayHttpUtil;
import com.ayf.payment.game.api.dto.GamePlayerCashOrderDTO;
import com.ayf.payment.game.api.dto.MerchantAlipayConfigDTO;
import com.ayf.payment.game.api.dto.alipay.AliOrderResult;
import com.ayf.payment.game.api.dto.alipay.AliOrderStatus;
import com.ayf.payment.game.api.dto.alipay.CallbackForm;
import com.ayf.payment.game.api.dto.alipay.MerchantAlipayOrderDTO;
import com.ayf.payment.game.api.entity.MerchantAlipayOrder;
import com.ayf.payment.game.api.service.GamePlayerCashOrderService;
import com.ayf.payment.game.api.service.MerchantAlipayConfigService;
import com.ayf.payment.game.api.service.MerchantAlipayOrderService;
import com.ayf.payment.game.api.utils.BigDecimalUtil;
import com.ayf.payment.game.api.utils.DateUtils;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * @Description: 支付宝代付实现
 * @Author: zh-liang
 * @Date : 2020-07-16 17:08
 */
@Component
public class AliPayServiceImpl implements AliPayService {
    private final static String serverUrl = System.getenv("GAME_ALI_PAY_SERVER_URL");
    private static final String QUERY_ORDER = "GAME_ALI_PAY_ORDER:";
    private final static Map<String, String> ownFailErrorCode = new HashMap<>();
    private final static Map<String, String> processingErrorCode = new HashMap<>();

    static {
        ownFailErrorCode.put("EXCEED_LIMIT_SM_AMOUNT", "交易失败，单笔额度超限");
        ownFailErrorCode.put("EXCEED_LIMIT_MM_AMOUNT", "交易失败，月累计金额超限");
        ownFailErrorCode.put("PAYCARD_UNABLE_PAYMENT", "交易失败，付款账户余额支付功能不可用");
        ownFailErrorCode.put("PAYER_STATUS_ERROR", "交易失败，付款账号状态异常");
        ownFailErrorCode.put("PAYER_CERTIFY_CHECK_FAIL", "交易失败，付款方人行认证受限");
        ownFailErrorCode.put("PAYER_BALANCE_NOT_ENOUGH", "交易失败，付款方余额不足");
        ownFailErrorCode.put("PAYER_USER_INFO_ERROR", "交易失败，付款用户姓名或其它信息不一致");
        ownFailErrorCode.put("CARD_BIN_ERROR", "交易失败，收款人银行账号不正确");
        ownFailErrorCode.put("PAYEE_CARD_INFO_ERROR", "交易失败，收款方卡信息错误");
        ownFailErrorCode.put("MEMO_REQUIRED_IN_TRANSFER_ERROR", "交易失败，根据监管部门的要求，单笔转账金额达到50000元时，需要填写付款理由");
        ownFailErrorCode.put("REMARK_HAS_SENSITIVE_WORD", "交易失败，转账备注包含敏感词，请修改备注文案后重试");
        ownFailErrorCode.put("EXCEED_LIMIT_DM_AMOUNT", "交易失败，日累计额度超限");
        ownFailErrorCode.put("NO_ACCOUNT_RECEIVE_PERMISSION", "交易失败，没有该账户的收款权限");
        ownFailErrorCode.put("BALANCE_IS_NOT_ENOUGH", "交易失败，付款方余额不足");
        ownFailErrorCode.put("PAYEE_NOT_EXIST", "交易失败，收款用户不存在");
        ownFailErrorCode.put("PAYEE_ACCOUNT_STATUS_ERROR", "交易失败，收款方账号异常");
        ownFailErrorCode.put("PERMIT_NON_BANK_LIMIT_PAYEE", "交易失败，收款方未完善身份信息或未开立余额账户，无法收款");
        ownFailErrorCode.put("PAYEE_TRUSTEESHIP_ACC_OVER_LIMIT", "交易失败，收款方托管子户累计收款金额超限");
        ownFailErrorCode.put("NO_PERMISSION_ACCOUNT", "交易失败，无权限操作当前付款账号");
        ownFailErrorCode.put("TRUSTEESHIP_ACCOUNT_NOT_EXIST", "交易失败，托管子户查询不存在");
        ownFailErrorCode.put("PAYEE_ACCOUNT_NOT_EXSIT", "交易失败，收款账号不存在");
        ownFailErrorCode.put("PAYEE_USERINFO_STATUS_ERROR", "交易失败，收款方用户状态不正常");
        ownFailErrorCode.put("PAYMENT_MONEY_NOT_ENOUGH", "交易失败，可用金额为0或不足");
        ownFailErrorCode.put("TRUSTEESHIP_RECIEVE_QUOTA_LIMIT", "交易失败，收款方收款额度超限，请绑定支付宝账户");
        ownFailErrorCode.put("PERM_AML_NOT_REALNAME_REV", "交易失败，根据监管部门的要求，需要收款用户补充身份信息才能继续操作");
        ownFailErrorCode.put("EXCEED_LIMIT_DC_RECEIVED", "交易失败，收款方单日收款笔数超限");
        ownFailErrorCode.put("PAYEE_ACC_OCUPIED", "交易失败，收款方登录号有多个支付宝账号，无法确认唯一收款账号");
        ownFailErrorCode.put("PAYER_PAYEE_CANNOT_SAME", "交易失败，收付款方不能相同");
        ownFailErrorCode.put("PERMIT_CHECK_PERM_LIMITED", "交易失败，根据监管部门的要求，请补全您的身份信息解除限制");
        ownFailErrorCode.put("EXCEED_LIMIT_DM_MAX_AMOUNT", "交易失败，超出单日转账限额");
        ownFailErrorCode.put("EXCEED_LIMIT_PERSONAL_SM_AMOUNT", "交易失败，超出转账给个人支付宝账户的单笔限额");
        ownFailErrorCode.put("EXCEED_LIMIT_UNRN_DM_AMOUN", "交易失败，收款账户未实名，超出其单日收款限额");
        ownFailErrorCode.put("INVALID_CARDNO", "交易失败，无效的收款卡号");
        ownFailErrorCode.put("RELEASE_USER_FORBBIDEN_RECIEVE", "交易失败，支付宝手机号二次放号禁止收款");
        ownFailErrorCode.put("PAYEE_USER_TYPE_ERROR", "交易失败，不支持的收款用户类型");
        ownFailErrorCode.put("EXCEED_LIMIT_SM_MIN_AMOUNT", "交易失败，请求金额低于单笔最小转账金额");
        ownFailErrorCode.put("PERMIT_CHECK_RECEIVE_LIMIT", "交易失败，您的账户限制收款，请咨询95188电话咨询");
        ownFailErrorCode.put("OVERSEA_TRANSFER_CLOSE", "交易失败，您无法进行结汇业务，请联系95188");
        ownFailErrorCode.put("PAYEE_NOT_RELNAME_CERTIFY", "交易失败，收款方未实名认证");
        ownFailErrorCode.put("INVALID_PARAMETER", "交易失败，请求参数有误");


        processingErrorCode.put("ORDER_NOT_EXIST", "");
        processingErrorCode.put("SYSTEM_ERROR", "");
        processingErrorCode.put("INVALID_PARAMETER", "");
        processingErrorCode.put("NO_ORDER_PERMISSION", "");
    }

    @Autowired
    private MerchantAlipayConfigService merchantAlipayConfigService;
    @Autowired
    private MerchantAlipayOrderService merchantAlipayOrderService;
    @Autowired
    private GamePlayerCashOrderService gamePlayerCashOrderService;
    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Override
    public void orderCreate(MerchantAlipayOrderDTO dto) {
        String traceId = dto.getTraceId();
        AliOrderResult aliOrderResult = new AliOrderResult();
        aliOrderResult.setMerchantOrderNo(dto.getMerchantOrderNo());
        aliOrderResult.setApplyTime(new Date());
        MerchantAlipayConfigDTO config = merchantAlipayConfigService.getAlipayConfigByMerchantId(dto.getMerchantId(),null);
        config.setServerUrl(serverUrl);
        aliOrderResult.setAppId(config.getAppId());
        aliOrderResult.setApplyTime(new Date());
        aliOrderResult.setSelfFlag(config.getSelfFlag());
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("out_biz_no", dto.getMerchantOrderNo());
        jsonParam.put("trans_amount", dto.getTransAmount());
        jsonParam.put("order_title", "转账");
        jsonParam.put("remark", dto.getRemark());// 业务备注
        if (dto.getPayType() == 1) {
            jsonParam.put("product_code", "TRANS_ACCOUNT_NO_PWD");
        } else {
            jsonParam.put("product_code", "TRANS_BANKCARD_NO_PWD");
        }
        JSONObject payeeInfoJsonParam = new JSONObject();
        payeeInfoJsonParam.put("identity", dto.getAccountNo());// 支付宝登录号，支持邮箱和手机号格式
        payeeInfoJsonParam.put("name", dto.getName());// 参与方真实姓名
        payeeInfoJsonParam.put("identity_type", "ALIPAY_LOGON_ID");
        jsonParam.put("payee_info", payeeInfoJsonParam);
        try {
            setOrderDelayQuery(dto.getMerchantOrderNo());
            LogPortal.info("{} 商户号[{}]商户订单号[{}]向支付宝下单的请求参数是:{}", traceId, dto.getMerchantId(), dto.getMerchantOrderNo(),
                    jsonParam.toJSONString());
            AlipayFundTransUniTransferResponse alipayFundTransUniTransferResponse = AlipayHttpUtil.createSinglePayOrder2(traceId, jsonParam, config);
            if (alipayFundTransUniTransferResponse == null) {
                aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
                aliOrderResult.setAliFailCode("ZDY_SYS_ERROR");
                aliOrderResult.setFailReason("支付渠道响应结果为空");
                LogPortal.error("{} 商户号[{}]商户订单号[{}]向支付宝下单失败，支付渠道返回结果为空", traceId, dto.getMerchantId(), dto.getMerchantOrderNo());
                merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
                if (dto.getOrderSource() != null && dto.getOrderSource() == 2) {
                    updateByMerChantOrderNo(aliOrderResult);
                }
                return;
            }
            LogPortal.info("{} 商户号[{}]商户订单号[{}]向支付宝下单成功，支付渠道返回报文:{}", traceId, dto.getMerchantId(), dto.getMerchantOrderNo(), alipayFundTransUniTransferResponse.getBody());
            aliOrderResult.setAliOrderId(alipayFundTransUniTransferResponse.getOrderId());
            if (!alipayFundTransUniTransferResponse.isSuccess()) {
                if ("SYSTEM_ERROR".equals(alipayFundTransUniTransferResponse.getSubCode())) {
                    aliOrderResult.setStatus(AliOrderStatus.PROCESSING.getCode());
                    aliOrderResult.setAliFailCode("SYSTEM_ERROR");
                    aliOrderResult.setFailReason("系统繁忙");
                    LogPortal.error("{} 商户号[{}]商户订单号[{}]向支付宝下单成功，支付渠道返回订单状态未明，支付渠道错误码[{}]错误描述[{}]", traceId, dto.getMerchantId(), dto.getMerchantOrderNo(), alipayFundTransUniTransferResponse.getSubCode(), alipayFundTransUniTransferResponse.getSubMsg());
                } else {
                    aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
                    aliOrderResult.setAliFailCode(alipayFundTransUniTransferResponse.getSubCode());
                    String failMsg = ownFailErrorCode.get(alipayFundTransUniTransferResponse.getSubCode());
                    failMsg = StringUtils.isEmpty(failMsg) ? "未知错误" : failMsg;
                    aliOrderResult.setFailReason(failMsg);
                    aliOrderResult.setAliFailMsg(alipayFundTransUniTransferResponse.getSubMsg());
                    aliOrderResult.setAliOrderId(alipayFundTransUniTransferResponse.getOrderId());
                    aliOrderResult.setAliPayFundOrderId(alipayFundTransUniTransferResponse.getPayFundOrderId());
                    LogPortal.error("ALIPAY_SINGLE_PAY_TRADE_EXCEPTION {} 商户号[{}]商户订单号[{}]向支付宝下单失败，支付渠道错误码[{}]错误描述[{}]", traceId, dto.getMerchantId(), dto.getMerchantOrderNo(), alipayFundTransUniTransferResponse.getSubCode(), alipayFundTransUniTransferResponse.getSubMsg());
                }
                merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
                if (dto.getOrderSource() != null && dto.getOrderSource() == 2) {
                    updateByMerChantOrderNo(aliOrderResult);
                }
                return;
            }
            aliOrderResult.setAliOrderId(alipayFundTransUniTransferResponse.getOrderId());
            aliOrderResult.setAliPayFundOrderId(alipayFundTransUniTransferResponse.getPayFundOrderId());
            aliOrderResult.setStatus(AliOrderStatus.PROCESSING.getCode());
            LogPortal.info("{} 商户号[{}]商户订单号[{}]向支付宝下单成功，响应:{}", traceId, dto.getMerchantId(), dto.getMerchantOrderNo(), aliOrderResult);
            merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
            if (dto.getOrderSource() != null && dto.getOrderSource() == 2) {
                updateByMerChantOrderNo(aliOrderResult);
            }
        } catch (AlipayApiException e) {
            Throwable throwable = e.getCause();
            if (throwable instanceof SocketTimeoutException) {
                aliOrderResult.setStatus(AliOrderStatus.PROCESSING.getCode());
                merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
                if (dto.getOrderSource() != null && dto.getOrderSource() == 2) {
                    updateByMerChantOrderNo(aliOrderResult);
                }
                return;
            }
            aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
            aliOrderResult.setFailReason(e.getMessage());
            LogPortal.error("ALIPAY_SINGLE_PAY_TRADE_EXCEPTION {} 商户号[{}]商户订单号[{}]向支付宝下单失败，异常信息为[{}]", traceId,
                    dto.getMerchantId(), dto.getMerchantOrderNo(), e.getMessage());
            LogPortal.error("{} 商户号[{}]商户订单号[{}]向支付宝下单失败,异常信息为[{}]", e, traceId, dto.getMerchantId(), dto.getMerchantOrderNo(),
                    e.getMessage());
            merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
            if (dto.getOrderSource() != null && dto.getOrderSource() == 2) {
                updateByMerChantOrderNo(aliOrderResult);
            }
        } catch (Exception e) {
            aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
            aliOrderResult.setFailReason(e.getMessage());
            LogPortal.error("ALIPAY_SINGLE_PAY_TRADE_EXCEPTION {} 商户号[{}]商户订单号[{}]向支付宝下单失败，失败原因是:{}", traceId, dto.getMerchantId(), dto.getMerchantOrderNo(), e.getMessage());
            LogPortal.error("{} 商户号[{}]商户订单号[{}]向支付宝下单失败，失败原因是:{}", e, traceId, dto.getMerchantId(), dto.getMerchantOrderNo(), e.getMessage());
            merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
            if (dto.getOrderSource() != null && dto.getOrderSource() == 2) {
                updateByMerChantOrderNo(aliOrderResult);
            }
        }
    }

    private void updateByMerChantOrderNo(AliOrderResult aliOrderResult) {
        GamePlayerCashOrderDTO gameDto = new GamePlayerCashOrderDTO();
        gameDto.setMerchantOrderNo(aliOrderResult.getMerchantOrderNo());
        gameDto.setStatus(aliOrderResult.getStatus());
        gameDto.setFailReason(aliOrderResult.getFailReason());
        if (AliOrderStatus.SUCCESS.getCode().equals(aliOrderResult.getStatus())) {
            gameDto.setFinishTime(aliOrderResult.getFinishTime());
            gameDto.setFailReason("付款成功");
        }
        gamePlayerCashOrderService.updateByMerChantOrderNo(gameDto);
    }

    @Override
    public Map<String, Object> balanceQuery(String traceId, Integer merchantId, String merchantOrderNo) {
        Map<String, Object> result = new HashMap<>();
        result.put("balance", BigDecimal.ZERO);
        result.put("status", "0");
        AliOrderResult aliOrderResult = new AliOrderResult();
        aliOrderResult.setMerchantOrderNo(merchantOrderNo);
        try {
            MerchantAlipayConfigDTO config = merchantAlipayConfigService.getAlipayConfigByMerchantId(merchantId,null);
            if (config == null || StringUtils.isEmpty(config.getPrivateKey())){
                result.put("msg", "支付宝通道参数未配置或者配置的不正确");
                return result;
            }
            config.setServerUrl(serverUrl);
            result.put("appId", config.getAppId());
            AlipayFundAccountQueryResponse alipayFundAccountQueryResponse = AlipayHttpUtil.queryAccountBalance2(traceId, config);
            if (alipayFundAccountQueryResponse == null) {
                result.put("msg", "支付渠道返回结果为空，请稍后重试");
                LogPortal.error("ALIPAY_BALANCE_QUERY_EXCEPTION {} 商户号[{}]商户订单号[{}]查询可用余额失败，支付渠道返回结果为空", traceId, merchantId, merchantOrderNo);
                return result;
            }
            if (!alipayFundAccountQueryResponse.isSuccess()) {
                result.put("msg", alipayFundAccountQueryResponse.getSubMsg());
                LogPortal.error("ALIPAY_BALANCE_QUERY_EXCEPTION {} 商户号[{}]商户订单号[{}]查询可用余额失败 支付渠道返回失败，错误码:{} 错误描述:{}", traceId, merchantId, merchantOrderNo, alipayFundAccountQueryResponse.getSubCode(), alipayFundAccountQueryResponse.getSubMsg());
                return result;
            }
            LogPortal.info("{} 商户号[{}]商户订单号[{}]查询可用余额成功，响应:{}", traceId, merchantId, merchantOrderNo, JSON.toJSONString(alipayFundAccountQueryResponse));
            BigDecimal balanceAmt = BigDecimalUtil.amtStrToBigdecimal(alipayFundAccountQueryResponse.getAvailableAmount());
            result.put("status", "1");
            result.put("balance",balanceAmt);
            return result;
        } catch (Exception e) {
            LogPortal.error("ALIPAY_BALANCE_QUERY_EXCEPTION {} 商户号[{}]商户订单号[{}]查询可用余额失败，发生了{}异常，失败原因是:{}", traceId, merchantId, merchantOrderNo, e.getClass().getName(), e.getMessage());
            LogPortal.error("{} 商户号[{}]商户订单号[{}]查询可用余额失败，发生了{}异常，失败原因是:{}", e, traceId, merchantId, merchantOrderNo, e.getClass().getName(), e.getMessage());
            result.put("msg", "未知异常：" + e.getMessage());
            return result;
        }
    }

    @Override
    public boolean callback(CallbackForm callbackForm) {
        String traceId = SnowFlakeUtils.getUniqueId();
        String type = "支付宝官方单笔代付";
        JSONObject dataJson = JSONObject.parseObject(callbackForm.getParameters().get("biz_content"));
        String merchantOrderNo = dataJson.getString("out_biz_no");
        String status = dataJson.getString("status");
        String aliOrderId = dataJson.getString("aliOrderId");
        String pay_date = dataJson.getString("pay_date");
        MerchantAlipayOrder payOrder = merchantAlipayOrderService.getRealTimePayOrder(merchantOrderNo);
        if (payOrder == null) {
            return false;
        }
        MerchantAlipayConfigDTO config = merchantAlipayConfigService.getAlipayConfigByMerchantId(payOrder.getMerchantId(),payOrder.getSelfFlag());
        config.setServerUrl(serverUrl);
        boolean checkSignResult = false;
        try {
            checkSignResult = AlipayHttpUtil.checkSyncNotifySign(callbackForm.getParameters(), config.getAlipayPublicCertBase64());
        } catch (Exception e) {
            LogPortal.info("ALIPAY_SINGLE_PAY_TRADE_NOTIFY_EXCEPTION {} {} 支付宝官方单笔转账异步通知-商户订单号[{}] 支付宝转账订单号[{}] " +
                    "验签发生{}异常,异常信息为[{}]", traceId, type, merchantOrderNo, aliOrderId, e.getClass().getName(), e.getMessage());
            LogPortal.info("{} {} 支付宝官方单笔转账异步通知-商户订单号[{}] 支付宝转账订单号[{}] 验签发生{}异常,异常信息为[{}]", e, traceId, type, merchantOrderNo, aliOrderId,
                    e.getClass().getName(), e.getMessage());
            return false;
        }
        LogPortal.info("{} {} 支付宝官方单笔转账异步通知-商户订单号[{}] 支付宝转账订单号[{}] 验签结果:{}", traceId, type, merchantOrderNo, aliOrderId,
                checkSignResult);
        if (!checkSignResult) {
            LogPortal.error("ALIPAY_SINGLE_PAY_TRADE_NOTIFY_EXCEPTION {} {} 支付宝官方单笔转账异步通知-商户订单号[{}] 支付宝转账订单号[{}] " +
                    "验签结果:{}", traceId, type, merchantOrderNo, aliOrderId, checkSignResult);
            return false;
        }
        MerchantAlipayOrder realTimePayOrder = merchantAlipayOrderService.getRealTimePayOrder(merchantOrderNo);
        if (realTimePayOrder == null) {
            LogPortal.info("{} 支付宝官方渠道后台 支付宝单笔代付异步通知-商户订单号[{}]支付宝转账订单号[{}] 交易记录不存在", traceId, merchantOrderNo, aliOrderId);
            return true;
        }
        if (AliOrderStatus.SUCCESS.getCode().equals(realTimePayOrder.getStatus())
                || AliOrderStatus.FAIL.getCode().equals(realTimePayOrder.getStatus())) {
            LogPortal.info("{} {} 支付宝官方单笔转账异步通知-商户订单号[{}]支付宝转账订单号[{}] 当前订单状态为:[{}] 状态已为终态，不再做处理", traceId, type,
                    merchantOrderNo, aliOrderId, realTimePayOrder.getStatus());
            return true;
        }
        if ("SUCCESS".equals(status)) { // 成功
            LogPortal.info("{} {} 支付宝官方单笔转账异步通知-商户订单号[{}]支付宝转账订单号[{}]交易成功", traceId, type, merchantOrderNo, aliOrderId);
            AliOrderResult aliOrderResult = new AliOrderResult();
            aliOrderResult.setMerchantOrderNo(merchantOrderNo);
            aliOrderResult.setAliOrderId(aliOrderId);
            aliOrderResult.setStatus(AliOrderStatus.SUCCESS.getCode());
            if (StringUtils.isNotEmpty(pay_date)) {
                aliOrderResult.setFinishTime(DateUtils.str2DateByFormat(pay_date, DateUtils.formatPattern_full));
            }
            merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
            if (realTimePayOrder.getOrderSource() != null && realTimePayOrder.getOrderSource() == 2) {
                updateByMerChantOrderNo(aliOrderResult);
            }
        } else {
            LogPortal.info("{} {} 支付宝官方单笔转账异步通知-商户订单号[{}]支付宝转账订单号[{}]交易状态未明，支付渠道状态[{}]，支付渠道错误码[{}]错误描述[{}]", traceId, type, merchantOrderNo, aliOrderId, status);
        }
        return true;
    }

    @Override
    public void queryOrderStatus(MerchantAlipayOrderDTO dto) {
        String traceId = dto.getTraceId();
        String tradeTypeMsg = "支付宝代付订单查询";
        AliOrderResult aliOrderResult = new AliOrderResult();
        aliOrderResult.setMerchantOrderNo(dto.getMerchantOrderNo());
        try {
            if (isDelayQuery(traceId, dto.getMerchantOrderNo())) {
                return;
            }
            MerchantAlipayOrder realTimePayOrder = merchantAlipayOrderService.getRealTimePayOrder(dto.getMerchantOrderNo());
            if (realTimePayOrder == null) {
                LogPortal.error("{} {}失败 商户号[{}]商户订单号[{}] 订单不存在", traceId, tradeTypeMsg, dto.getMerchantId(), dto.getMerchantOrderNo());
                return;
            }
            if (realTimePayOrder.getStatus().equals(AliOrderStatus.SUCCESS.getCode()) || realTimePayOrder.getStatus().equals(AliOrderStatus.FAIL.getCode())) {
                LogPortal.error("{} {}失败 商户号[{}]商户订单号[{}] 订单已是终态，无需继续查询", traceId, tradeTypeMsg, dto.getMerchantId(), dto.getMerchantOrderNo());
                return;
            }
            LogPortal.info("{} {} 商户号[{}]商户订单号[{}] ", traceId, tradeTypeMsg, dto.getMerchantId(), dto.getMerchantOrderNo());
            MerchantAlipayConfigDTO config = merchantAlipayConfigService.getAlipayConfigByMerchantId(dto.getMerchantId(),realTimePayOrder.getSelfFlag());
            config.setServerUrl(serverUrl);
            AlipayFundTransCommonQueryResponse alipayFundTransCommonQueryResponse = AlipayHttpUtil.querySinglePayOrder2(traceId, dto.getMerchantOrderNo(), config);
            if (alipayFundTransCommonQueryResponse == null) {
                LogPortal.error("{} {}失败 商户号[{}]商户订单号[{}] 支付渠道响应结果为空 结束当前查询，继续等待下一轮任务执行进行查询", traceId, tradeTypeMsg, dto.getMerchantId(), dto.getMerchantOrderNo());
                return;
            }
            LogPortal.info("{} {}成功 商户号[{}]商户订单号[{}]  支付渠道响应结果为:{}", traceId, tradeTypeMsg, dto.getMerchantId(), dto.getMerchantOrderNo(), JSONObject.toJSONString(alipayFundTransCommonQueryResponse.getBody()));

            if (!alipayFundTransCommonQueryResponse.isSuccess()) {
                if (processingErrorCode.containsKey(alipayFundTransCommonQueryResponse.getSubCode())) {
                    LogPortal.error("{} {}失败 商户号[{}]商户订单号[{}]  支付渠道响应结果不明确 结束当前查询，继续等待下一轮任务执行进行查询", traceId,
                            tradeTypeMsg, dto.getMerchantId(), dto.getMerchantOrderNo());
                    return;
                }
            }
            if (StringUtils.isNotEmpty(alipayFundTransCommonQueryResponse.getSubCode())
                    && ownFailErrorCode.containsKey(alipayFundTransCommonQueryResponse.getSubCode())) {
                LogPortal.info("{} {}成功 商户号[{}]商户订单号[{}]  支付渠道返回订单状态为空，错误码[{}]错误描述[{}]", traceId, tradeTypeMsg,
                        dto.getMerchantId(), dto.getMerchantOrderNo(), alipayFundTransCommonQueryResponse.getSubCode(), alipayFundTransCommonQueryResponse.getSubMsg());
                aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
                String failMsg = ownFailErrorCode.get(alipayFundTransCommonQueryResponse.getSubCode());
                failMsg = StringUtils.isEmpty(failMsg) ? alipayFundTransCommonQueryResponse.getSubMsg() : failMsg;
                aliOrderResult.setFailReason(failMsg);
                aliOrderResult.setAliFailCode(alipayFundTransCommonQueryResponse.getSubCode());
                aliOrderResult.setAliFailMsg(alipayFundTransCommonQueryResponse.getSubMsg());
                merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
                if (realTimePayOrder.getOrderSource() != null && realTimePayOrder.getOrderSource() == 2) {
                    updateByMerChantOrderNo(aliOrderResult);
                }
                return;
            }
            if (StringUtils.isNotEmpty(alipayFundTransCommonQueryResponse.getStatus())) {
                if ("SUCCESS".equals(alipayFundTransCommonQueryResponse.getStatus())) {
                    aliOrderResult.setStatus(AliOrderStatus.SUCCESS.getCode());
                    if (StringUtils.isNotEmpty(alipayFundTransCommonQueryResponse.getOrderFee())) {
                        aliOrderResult.setFee(new BigDecimal(alipayFundTransCommonQueryResponse.getOrderFee()));
                    }
                    if (StringUtils.isNotEmpty(alipayFundTransCommonQueryResponse.getPayDate())) {
                        aliOrderResult.setFinishTime(DateUtils.str2DateByFormat(alipayFundTransCommonQueryResponse.getPayDate(),
                                DateUtils.formatPattern_full));
                    }
                    aliOrderResult.setAliOrderId(alipayFundTransCommonQueryResponse.getOrderId());
                    merchantAlipayOrderService.updateOrderStatus(aliOrderResult);
                    if (realTimePayOrder.getOrderSource() != null && realTimePayOrder.getOrderSource() == 2) {
                        updateByMerChantOrderNo(aliOrderResult);
                    }
                    return;
                }
                if ("FAIL".equals(alipayFundTransCommonQueryResponse.getStatus())
                        || "CLOSED".equals(alipayFundTransCommonQueryResponse.getStatus())) {
                    LogPortal.info("{} {}成功 商户号[{}]商户订单号[{}]  支付渠道返回订单状态:{}，错误码[{}]错误描述[{}]", traceId, tradeTypeMsg,
                            dto.getMerchantId(), dto.getMerchantOrderNo(), alipayFundTransCommonQueryResponse.getStatus(), alipayFundTransCommonQueryResponse.getErrorCode(), alipayFundTransCommonQueryResponse.getFailReason());
                    aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
                    aliOrderResult.setFailReason("CLOSED".equals(alipayFundTransCommonQueryResponse.getStatus()) ? "订单超时关闭" :
                            alipayFundTransCommonQueryResponse.getFailReason());
                    aliOrderResult.setAliFailCode(alipayFundTransCommonQueryResponse.getErrorCode());
                    aliOrderResult.setAliFailMsg(alipayFundTransCommonQueryResponse.getFailReason());
                    aliOrderResult.setAliOrderId(alipayFundTransCommonQueryResponse.getOrderId());
                    if (realTimePayOrder.getOrderSource() != null && realTimePayOrder.getOrderSource() == 2) {
                        updateByMerChantOrderNo(aliOrderResult);
                    }
                }
            }
        } catch (Exception e) {
            LogPortal.error("ALIPAY_SINGLE_PAY_TRADE_QUERY_EXCEPTION {} {}失败 商户订单号[{}]  支付渠道发生{}异常，原因:{}", traceId,
                    tradeTypeMsg, dto.getMerchantId(), dto.getMerchantOrderNo(), e.getClass().getName(), e.getMessage());
            LogPortal.error("{} {}失败 商户号[{}]商户订单号[{}]  支付渠道发生{}异常，原因:{}", e, traceId, tradeTypeMsg, dto.getMerchantId(),
                    dto.getMerchantOrderNo(), e.getClass().getName(), e.getMessage());
        }
    }


    /**
     * 延迟2分钟进行查询
     *
     * @param orderNo
     */
    private void setOrderDelayQuery(String orderNo) {
        String redisKey = QUERY_ORDER.concat(orderNo);
        redisCacheUtil.setObjectToCacheDelaySeconds(redisKey, "delayQuery", 120L);
    }

    /**
     * 是否延迟查询
     *
     * @param orderNo
     * @return
     */
    private boolean isDelayQuery(String traceId, String orderNo) {
        String redisKey = QUERY_ORDER.concat(orderNo);
        if (redisCacheUtil.getObjectFromCache(redisKey) == null) {
            return false;
        }
        LogPortal.info("{} 订单号:{}延迟查询", traceId, orderNo);
        return true;
    }
}
